package com.lixia.lxframework.framework.utils.file;


import com.lixia.lxframework.framework.system.constant.SymbolConstant;
import com.lixia.lxframework.framework.system.ex.BusinessException;
import com.lixia.lxframework.framework.utils.IdUtils;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

import static com.lixia.lxframework.framework.system.constant.Constants.*;

/**
 * 文件上传工具类
 *
 * @author Mr.wang
 */
public class FileUtils {

    private static final Logger logger = LoggerFactory.getLogger(FileUtils.class);

    /**
     * 上传
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static FileInfo uploadFile(MultipartFile file, String directoryPrefix) throws Exception {
        return uploadFile(file, directoryPrefix, true);
    }

    /**
     * 上传图片
     *
     * @param file            文件
     * @param directoryPrefix 目录前缀
     * @param isRandomName    是否随机名称
     * @return 文件信息
     */
    public static FileInfo uploadFile(MultipartFile file, String directoryPrefix, boolean isRandomName) {
        if (ObjectUtils.isEmpty(file)) {
            throw new BusinessException("没有找到相对应的文件！");
        }
        // 存放位置(路径)
        String filePath = directoryPrefix + UPLOAD_FILE_DIRECTORY;
        // 文件原名称
        String originalFileName = file.getOriginalFilename();
        logger.info("上传的文件原名称：[{}]", originalFileName);
        String fileType = getExtensionName(originalFileName);
        if (StringUtils.isEmpty(fileType)) {
            throw new BusinessException("文件类型不能为空！");
        }
        String relativePath;
        FileInfo fileInfo = new FileInfo();
        try {
            // 文件名
            String fileName;
            // 存放文件的路径
            if (isRandomName) {
                fileName = getUUIDFileName(originalFileName);
            } else {
                fileName = originalFileName;
            }
            createDir(filePath);
            // 上传文件
            relativePath = filePath + fileName;
            File targetFile = new File(relativePath);
            file.transferTo(targetFile);
            fileInfo.setFileName(UPLOAD_FILE_DIRECTORY + fileName);
            fileInfo.setOriginalFileName(originalFileName);
            String extensionName = fileType.toUpperCase();
            Integer fileSize = (int) (file.getSize() / 1024);
            fileInfo.setFileSize(fileSize);
            if (isPicture(extensionName)) {
                fileInfo.setFileType("PICTURE");
                saveThumbnail(relativePath);
            }
        } catch (Exception e) {
            logger.error("上传文件失败!", e);
            throw new BusinessException("上传文件失败！", e);
        }
        return fileInfo;
    }

    /**
     * 根据扩展名判断文件类型
     *
     * @param extensionName 文件扩展名
     * @return 是否图片
     */
    public static boolean isPicture(String extensionName) {
        extensionName = extensionName.toUpperCase();
        return ATTACHMENT_SUFFIX_JPG.equals(extensionName) || ATTACHMENT_SUFFIX_JPEG.equals(extensionName) || ATTACHMENT_SUFFIX_PNG.equals(extensionName) || ATTACHMENT_SUFFIX_GIF.equals(extensionName) || ATTACHMENT_SUFFIX_BMP.equals(extensionName);
    }

    /**
     * 创建文件目录
     *
     * @param dirPath 要创建的目录
     */
    public static void createDir(String dirPath) {
        if (StringUtils.isEmpty(dirPath)) {
            return;
        }
        File file = new File(dirPath);
        if (!file.exists()) {
            //在linux 下java 的默认的文件写入权限仅局限在执行目录之下
            file.setWritable(true, false);
            file.mkdirs();
        }
    }

    /**
     * 获取不带后缀的文件名
     *
     * @param fileName 文件名
     * @return
     */
    public static String getFileNameWithoutSuffix(String fileName) {
        String _fileName = "";
        if (!StringUtils.isEmpty(fileName)) {
            _fileName = fileName.substring(0, fileName.lastIndexOf("."));
        }
        return _fileName;
    }

    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名
     * @return
     */
    public static String getExtensionName(String fileName) {
        String extension = "";
        if (!StringUtils.isEmpty(fileName)) {
            int lastIndex = fileName.lastIndexOf('.');
            lastIndex = lastIndex > 0 ? lastIndex + 1 : 0;
            extension = fileName.substring(lastIndex);
        }
        return extension;
    }

    /**
     * 给文件生成UUID 文件名
     *
     * @param fileName 文件名
     * @return 新文件名
     */
    public static String getUUIDFileName(String fileName) {
        StringBuilder newName = new StringBuilder();
        if (!StringUtils.isEmpty(fileName)) {
            newName.append(IdUtils.simpleUUID());
            newName.append('.');
            newName.append(getExtensionName(fileName));
        }
        return newName.toString();
    }

    /**
     * 文件文件缩略图
     *
     * @param filePath 文件路径
     * @return
     */
    public static String getThumbnailFilePath(String filePath) {
        StringBuilder thumbnailFilePath = new StringBuilder();
        if (!StringUtils.isEmpty(filePath)) {
            int lastIndex = filePath.lastIndexOf(SymbolConstant.SYMBOL_DOT);
            lastIndex = Math.max(lastIndex, 0);
            thumbnailFilePath.append(filePath, 0, lastIndex);
            thumbnailFilePath.append(ATTACHMENT_SHORT_PICTURE_SUFFIX);
            thumbnailFilePath.append(SymbolConstant.SYMBOL_DOT);
            thumbnailFilePath.append(getExtensionName(filePath));
        }
        return thumbnailFilePath.toString();
    }

    public static void saveThumbnail(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            return;
        }
        String thumbnailFilePath = getThumbnailFilePath(filePath);
        try {
            Thumbnails.of(filePath).size(130, 92).toFile(thumbnailFilePath);
        } catch (Exception e) {
            throw new BusinessException("上传文件缩略图失败!", e);
        }
    }

    public static void writeStream(InputStream is, OutputStream os) throws Exception {
        byte[] buff = new byte[1024];
        int readCount = 0;
        readCount = is.read(buff);
        while (readCount != -1) {
            os.write(buff, 0, readCount);
            readCount = is.read(buff);
        }
    }

    /**
     * 删除指定文件夹下所有文件
     * param path 文件夹完整绝对路径
     *
     * @param path
     * @return
     */
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }
        if (!file.isDirectory()) {
            return false;
        }
        String[] tempList = file.list();
        File temp = null;
        assert tempList != null;
        for (String s : tempList) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + s);
            } else {
                temp = new File(path + File.separator + s);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                //先删除文件夹里面的文件
                delAllFile(path + "/" + s);
                //再删除空文件夹
                delFolder(path + "/" + s);
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 删除指定文件夹下的所有文件及空文件夹
     *
     * @param folderPath
     */
    public static void delFolder(String folderPath) {
        try {
            //删除完里面所有内容
            delAllFile(folderPath);
            String filePath = folderPath;
            File myFilePath = new File(filePath);
            //删除空文件夹
            myFilePath.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 文件移动
     *
     * @param srcPathStr 源地址
     * @param desPathStr 目标地址
     */
    public static void copy(String srcPathStr, String desPathStr) {
        //获取源文件的名称
        FileInputStream fis = null;
        FileOutputStream fos = null;
        //目标文件地址
        String newFileName = srcPathStr.substring(srcPathStr.lastIndexOf("\\") + 1);
        File desFile = new File(desPathStr);
        if (!desFile.exists()) {
            desFile.mkdirs();
        }
        try {
            //源文件地址
            desPathStr = desPathStr + File.separator + newFileName;
            //创建输入流对象
            fis = new FileInputStream(srcPathStr);
            //创建输出流对象
            fos = new FileOutputStream(desPathStr);
            //创建搬运工具
            byte[] datas = new byte[1024 * 8];
            //创建长度
            int len = 0;
            //循环读取数据
            while ((len = fis.read(datas)) != -1) {
                fos.write(datas, 0, len);
            }
        } catch (IOException e) {
            throw new BusinessException("文件移动失败!", e);
        } finally {
            try {//释放资源
                fis.close();
                fis.close();
            } catch (IOException e) {
                throw new BusinessException("文件移动失败!", e);
            }
        }
    }
}
